package com.mysoft.gfyx.clue.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mysoft.framework.common.exception.BusinessLogicException;
import com.mysoft.framework.common.user.User;
import com.mysoft.framework.common.util.MappingUtil;
import com.mysoft.framework.context.api.ContextManager;
import com.mysoft.framework.context.info.ContextInfo;
import com.mysoft.framework.core.function.authorization.AuthenticationUser;
import com.mysoft.framework.modeling.dto.*;
import com.mysoft.framework.sdk.system.api.SystemDataProvider;
import com.mysoft.framework.sdk.system.dto.UserDTO;
import com.mysoft.framework.service.AppService;
import com.mysoft.gfyx.clue.controller.dto.*;
import com.mysoft.gfyx.clue.controller.dto.Perm.GetUserBUDataPermissionResponseDto;
import com.mysoft.gfyx.clue.dao.ClueDao;
import com.mysoft.gfyx.clue.dao.CluecontacterDao;
import com.mysoft.gfyx.clue.dao.CluefollowprojectinfoDao;
import com.mysoft.gfyx.clue.dao.CluefollowrecordDao;
import com.mysoft.gfyx.clue.dao.dto.MyClueRequestDto;
import com.mysoft.gfyx.clue.dao.entity.*;
import com.mysoft.gfyx.clue.mip.FuzzySearchService;
import com.mysoft.gfyx.clue.mip.dto.FuzzySearchReqDto;
import com.mysoft.gfyx.clue.remoteservice.RemoteDeveloperService;
import com.mysoft.gfyx.clue.remoteservice.RemoteOpptyStatusService;
import com.mysoft.gfyx.clue.remoteservice.RemoteSystemService;
import com.mysoft.gfyx.clue.remoteservice.dto.GetPurchaseContactsRequestDto;
import com.mysoft.gfyx.clue.remoteservice.dto.UpdateOpptyStatusRequestDto;
import com.mysoft.gfyx.clue.service.*;
import com.mysoft.gfyx.clue.service.dto.*;
import com.mysoft.gfyx.common.dto.GetInfoByIdRequestDto;
import com.mysoft.gfyx.common.dto.TotalDto;
import com.mysoft.gfyx.common.rpc.mpapi.MpapiClientFactoryService;
import com.mysoft.gfyx.common.rpc.mpapi.MpapiClientService;
import com.mysoft.gfyx.common.rpc.mpapi.dto.ClueToCrmRequestDto;
import com.mysoft.sdk.context.core.ThreadContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 描述：Clue 业务代码
 *
 * @author JavaSdk generator
 * @date 2022-07-07
 */
@Service
public class ClueServiceImp extends AppService implements ClueService {
    @Autowired
    private CluecontacterService cluecontacterService;

    @Autowired
    private ClueDao clueDao;

    @Autowired
    private CluecontacterDao cluecontacterDao;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private ContextManager contextManager;

    @Autowired
    private RemoteDeveloperService remoteDeveloperService;

    @Autowired
    private RemoteSystemService remoteSystemMessageService;

    @Autowired
    private DataPermissionService dataPermissionService;

    @Autowired
    private CluefollowrecordDao cluefollowrecordDao;

    @Autowired
    private CluefollowprojectinfoDao cluefollowprojectinfoDao;

    @Autowired
    private CustomerPoolService customerPoolService;

    @Autowired
    private CustomerHistoryService customerHistoryService;

    @Autowired
    private FuzzySearchService fuzzySearchService;

    @Autowired
    private MpapiClientFactoryService mpapiClientFactoryService;
    @Autowired
    private SystemDataProvider systemDataProvider;

    @Autowired
    private RemoteOpptyStatusService remoteOpptyStatusService;

    public int countDeveloperClue(String developerCreditCode) {
        User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);

        QueryWrapper<Clue> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("CreditCode", developerCreditCode);
        queryWrapper.eq("ClueResponsiblePersonGUID", authenticationUser.getUserId());

        return clueDao.selectCount(queryWrapper).intValue();
    }

    @Override
    public int getMyClueCount() {
        ContextInfo contextInfo = contextManager.fetchContextInfo();
        UUID userId = contextInfo.getUserContext().getUserId();
        QueryWrapper<Clue> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ClueResponsiblePersonGUID", userId);
        return clueDao.selectCount(queryWrapper).intValue();
    }

    public boolean changeCooperationStatus(Integer status, UUID id) {
        ClueDto clueDto = new ClueDto();
        clueDto.setClueStatus(status);
        updateById(clueDto, id);
        return true;
    }

    public boolean updateById(ClueDto clueDto, UUID id) {
        Clue clue = MappingUtil.getSimpleMapperFacade().map(clueDto, Clue.class);
        clue.setClueGUID(id);
        clueDao.updateById(clue);

        return true;
    }

    @Transactional
    public Clue checkAndAddClue(AddClueRequestDto request) {
        // 检查
        checkClueAddition(request);

        // 第一步，添加到客户池
        CustomerPoolDto customerPoolDto = this.addCustomerPool(request);
        // 第二步，检查客户是否存在，如果不存在，则创建客户
        CustomerDto customerDto = this.addCustomer(request, customerPoolDto);
        request.setCustomerGUID(customerDto.getCustomerGUID());

        // 第三步，尝试增加这个线索
        // 目前直接把线索的省市设置为开发商的省市，项目的省市进关联表
        setCLueArea(request, customerDto);
        ClueDto clueDto = MappingUtil.getSimpleMapperFacade().map(request, ClueDto.class);

        List<Cluefollowprojectinfo> cluefollowprojectinfos = request.getClueSourceProjectList().stream().map(p -> MappingUtil.getSimpleMapperFacade().map(p, Cluefollowprojectinfo.class)).collect(Collectors.toList());
        Clue clue = this.addClue(clueDto, cluefollowprojectinfos);

        // 第四步,把线索数据同步至客户的CRM系统,该业务逻辑在go的商机服务实现,这里需要调用其方法

        ClueToCrmRequestDto requestDto = new ClueToCrmRequestDto();
        String tenantCode = contextManager.fetchContextInfo().getTenantCode();
        MpapiClientService remoteService = mpapiClientFactoryService.getMpapiClientService();
        requestDto.setClue_guid(clue.getClueGUID().toString());
        requestDto.setTenant_code(tenantCode);
        requestDto.setContacter_name(clue.getContacterName());
        requestDto.setContacter_tel(clue.getContacterTel());
        requestDto.setProvince_name(clue.getProvinceName());
        requestDto.setCustomer_name(clue.getCustomerName());
        UserDTO userDTO = systemDataProvider.getUser(clue.getClueResponsiblePersonGUID().toString());
        if (userDTO != null) {
            requestDto.setResponsible_person_mobile(userDTO.getCellphone());
        }
        remoteService.ClueToCrm(requestDto);

        // 第五步 更新数据状态
        UpdateOpptyStatusRequestDto updateOpptyStatusRequestDto = new UpdateOpptyStatusRequestDto();
        updateOpptyStatusRequestDto.setDataSource(request.getClueSource());
        updateOpptyStatusRequestDto.setDataSourceId(request.getClueSourceId());
        updateOpptyStatusRequestDto.setStatus(RemoteOpptyStatusService.OpptyStatus.NUM3.ordinal());
        remoteOpptyStatusService.updateOpptyStatus(updateOpptyStatusRequestDto);

        return clue;
    }

    protected CustomerDto addCustomer(AddClueRequestDto request, CustomerPoolDto customerPoolDto) {
        Map<String, Object> conditions = new HashMap<>();
        conditions.put("CreditCode", request.getCreditCode());
        conditions.put("customerResponsiblePersonGUID", request.getClueResponsiblePersonGUID());
        conditions.put("__IsDeleted", 0);
        CustomerDto customerDto = customerService.getCustomer(conditions);
        if (customerDto == null) {
            customerDto = MappingUtil.getSimpleMapperFacade().map(request, CustomerDto.class);
            customerDto.setCooperationStatus(CustomerService.COOPERATION_STATUS_NEVER);
            customerDto.setCustomerResponsiblePersonGUID(request.getClueResponsiblePersonGUID());
            customerDto.setCustomerResponsiblePersonName(request.getClueResponsiblePersonName());
            customerDto.setCustomerPoolGUID(customerPoolDto.getCustomerPoolGUID());
            UUID batchId = UUID.randomUUID();
            customerDto.setBatchID(batchId);
            Customer entity = customerService.addCustomer(customerDto);
            customerDto.setCustomerGUID(entity.getCustomerGUID());
        }
        //添加到历史记录表
        Map<String, Object> conditionsHis = new HashMap<>();
        conditionsHis.put("CreditCode", request.getCreditCode());
        conditionsHis.put("customerResponsiblePersonGUID", request.getClueResponsiblePersonGUID());
        CustomerHistoryDto customerHistoryDto = customerHistoryService.getCustomerHistory(conditionsHis);
        if (customerHistoryDto == null) {
            customerHistoryDto = MappingUtil.getSimpleMapperFacade().map(customerDto, CustomerHistoryDto.class);
            customerHistoryService.addCustomerHistory(customerHistoryDto);
        }
        // 重新查找，可以优化
        customerDto = customerService.getCustomer(conditions);
        return customerDto;
    }

    protected CustomerPoolDto addCustomerPool(AddClueRequestDto request) {
        Map<String, Object> conditions = new HashMap<>();
        conditions.put("CreditCode", request.getCreditCode());
        conditions.put("__IsDeleted", 0);
        CustomerPoolDto customerPoolDto = customerPoolService.getCustomerPool(conditions);
        if (customerPoolDto == null) {
            customerPoolDto = MappingUtil.getSimpleMapperFacade().map(request, CustomerPoolDto.class);
            customerPoolDto.setCooperationStatus(CustomerService.COOPERATION_STATUS_NEVER);
            customerPoolDto.setAssignStatus(CustomerPoolService.ASSIGN_STATUS_HAS);
            CustomerPool res = customerPoolService.addCustomerPool(customerPoolDto);
            customerPoolDto.setCustomerPoolGUID(res.getCustomerPoolGUID());
        } else {
            customerPoolDto.setAssignStatus(CustomerPoolService.ASSIGN_STATUS_HAS);
            UUID res = customerPoolService.editCustomerPool(customerPoolDto);
        }
        return customerPoolDto;
    }

    protected void setCLueArea(AddClueRequestDto request, CustomerDto customerDto) {
        if (request.getClueSourceProjectList().size() > 0) {
            String cityCode = "", provinceCode = "";
            List<String> province = request.getClueSourceProjectList().stream().map(p -> p.getProjectAreaProvince()).collect(Collectors.toList());
            List<String> city = request.getClueSourceProjectList().stream().map(p -> p.getProjectAreaCity()).collect(Collectors.toList());
            Iterator<AddClueRequestDto.ClueSourceProject> it = request.getClueSourceProjectList().iterator();
            while (it.hasNext()) {
                AddClueRequestDto.ClueSourceProject s = it.next();
                cityCode += "[" + s.getProjectAreaCityCode() + "]";
                provinceCode += "[" + s.getProjectAreaProvinceCode() + "]";
            }
            request.setAreaCategoryCode(cityCode);
            request.setAreaCategoryName(String.join(",", city));
            request.setProvinceCode(provinceCode);
            request.setProvinceName(String.join(",", province));
        } else {
            request.setAreaCategoryCode("[" + customerDto.getAreaCategoryCode() + "]");
            request.setAreaCategoryName(customerDto.getAreaCategoryName());
            request.setProvinceCode("[" + customerDto.getProvinceCode() + "]");
            request.setProvinceName(customerDto.getProvinceName());
        }
    }

    protected void checkClueAddition(AddClueRequestDto request) {
        // 前置条件，如果存在线索来源，则将项目信息信息带入上下文
        if (request.getClueSourceId() != null) {
            GetPurchaseContactsRequestDto getPurchaseContactsRequestDto = new GetPurchaseContactsRequestDto();
            getPurchaseContactsRequestDto.setId(request.getClueSourceId());
            List<Map<String, Object>> projectsList = remoteDeveloperService.getPurchaseProjects(getPurchaseContactsRequestDto);
            projectsList.forEach(p -> {
                AddClueRequestDto.ClueSourceProject clueSourceProject = new AddClueRequestDto.ClueSourceProject();
                clueSourceProject.setProjectName(p.getOrDefault("project_name", "").toString());
                clueSourceProject.setProjectAreaProvinceCode(p.getOrDefault("province_code", "").toString());
                clueSourceProject.setProjectAreaProvince(p.getOrDefault("province", "").toString());
                clueSourceProject.setProjectAreaCityCode(p.getOrDefault("city_code", "").toString());
                clueSourceProject.setProjectAreaCity(p.getOrDefault("city", "").toString());
                request.getClueSourceProjectList().add(clueSourceProject);
            });
        }

        // 负责人
        if (request.getClueResponsiblePersonGUID() == null) {
            request.setClueResponsiblePersonGUID(contextManager.fetchContextInfo().getUserContext().getUserId());
            request.setClueResponsiblePersonName(contextManager.fetchContextInfo().getUserContext().getUserName());
        }

        // 前置条件，如果当前用户所在的组织被区域权限所限制，那么需要判断该线索的区域它能否加入
        areaAdditionAllowed(request);

        // 前置条件，如果存在contacterId，则远程获取contacter的信息取代打码信息
        if (request.getContacterId() != null && request.getContacterId() != "") {
            Map<String, Object> info = getRemoteContactInfo(request.getContacterId());
            Object ower = info.get("ower");
            if (ower != null && !ower.equals("")) {
                request.setContacterName(info.getOrDefault("ower", request.getContacterName()).toString());
            }
            request.setContacterTel(info.getOrDefault("ower_mobile", request.getContacterTel()).toString());
        }
    }

    protected void areaAdditionAllowed(AddClueRequestDto request) {
        // 如果是从线索管理里面添加的线索，checkArea字段值为1，表示不需要校验地区
        if (request.getCheckArea() != null && request.getCheckArea() != 0) {
            return;
        }

        UUID userUUID = request.getClueResponsiblePersonGUID();
        if (userUUID == null) {
            userUUID = contextManager.fetchContextInfo().getUserContext().getUserId();
        }
        UserDTO userDTO = remoteSystemMessageService.GetUser(userUUID.toString());
        if (userDTO == null) {
            throw new BusinessLogicException("非法的用户请求");
        }
        GetUserBUDataPermissionResponseDto permissions = dataPermissionService.getUserBUDataPermission(DataPermissionService.DataPermissionType.CustomerClue, UUID.fromString(userDTO.getBuGuid()));
        if (permissions.isExistBUPermission()) {
            // 只有用户的BU设置了权限才需要进行这一步检查
            String[] areaList = permissions.getArea().split(",");
            HashSet<String> allowedArea = new HashSet<>();
            boolean hasPermission = false;
            for (String area : areaList) {
                if (area.equals("0")) {
                    return;
                }
                allowedArea.add(area);
            }

            if (request.getClueSourceProjectList().size() > 0) {
                // 如果项目地区和允许区域没有交集，则禁止
                Iterator<AddClueRequestDto.ClueSourceProject> it = request.getClueSourceProjectList().iterator();
                boolean projectHaveAreaInfo = false;
                while (it.hasNext()) {
                    AddClueRequestDto.ClueSourceProject p = it.next();
                    if ((p.getProjectAreaCityCode() != null && p.getProjectAreaCityCode().length() > 0) || (p.getProjectAreaProvinceCode() != null && p.getProjectAreaProvinceCode().length() > 0)) {
                        projectHaveAreaInfo = true;
                    }
                    if (allowedArea.contains(p.getProjectAreaCityCode()) || allowedArea.contains(p.getProjectAreaProvinceCode())) {
                        hasPermission = true;
                    } else {
                        // 如果这个项目不在该人负责区域则删除
                        it.remove();
                    }
                }
                // 当项目没有地址，则谁都可以添加
                if (!projectHaveAreaInfo) {
                    hasPermission = true;
                }
            } else if ((request.getProvinceCode() != null && request.getProvinceCode().length() > 0) || (request.getAreaCategoryCode() != null && request.getAreaCategoryCode().length() > 0)) {
                if (allowedArea.contains(request.getProvinceCode()) || allowedArea.contains(request.getAreaCategoryCode())) {
                    hasPermission = true;
                }
            } else {
                // 如果项目为空，并且开发商省市也为空，则不检测
                return;
            }

            if (!hasPermission) {
                throw new BusinessLogicException("该线索的项目所在地不在线索负责人所在组织的权限内，请联系管理员配置权限");
            }
        }
    }

    public Clue addClue(ClueDto clueDto, List<Cluefollowprojectinfo> cluefollowprojectinfos) {
        // 第一步，检查是否增加过同样的线索
        //User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);
        Map<String, Object> conditions = new HashMap<>();
        conditions.put("CustomerGUID", clueDto.getCustomerGUID());
        conditions.put("ClueResponsiblePersonGUID", clueDto.getClueResponsiblePersonGUID());
        conditions.put("ContacterTel", clueDto.getContacterTel());
        if (clueDto.getClueSourceId() != null) {
            conditions.put("ClueSource", clueDto.getClueSource());
            conditions.put("ClueSourceId", clueDto.getClueSourceId());
        }
        ClueDto existClueDto = getClue(conditions);
        if (existClueDto != null) {
            Clue c = MappingUtil.getSimpleMapperFacade().map(existClueDto, Clue.class);
            return c;
            // throw new BusinessLogicException("您曾经添加过这个线索了");
        }

        // 第二步，增加这个线索
        Clue c = MappingUtil.getSimpleMapperFacade().map(clueDto, Clue.class);
        if (c.getFrom_device() == null) {
            c.setFrom_device("PC");
        }

        c.setNewAddition(true);
        clueDao.insert(c);

        // 第三步，增加这个线索的项目信息
        if (cluefollowprojectinfos != null && cluefollowprojectinfos.size() > 0) {
            cluefollowprojectinfos.forEach(p -> {
                p.setClueGUID(c.getClueGUID());
                p.setCustomerName(c.getCustomerName());
                p.setCreditCode(c.getCreditCode());
            });
            cluefollowprojectinfoDao.insertBatchWithDynamicExt(cluefollowprojectinfos);
        }

        // 第四步，增加这个线索的联系人
        ClueContacterDto clueContacterDto = cluecontacterService.getClueContacterByClueTel(c.getClueGUID(), clueDto.getContacterTel());
        if (clueContacterDto == null) {
            Cluecontacter cluecontacter = new Cluecontacter();
            cluecontacter.setClueGUID(c.getClueGUID());
            cluecontacter.setContacterName(clueDto.getContacterName());
            cluecontacter.setCompanyTel(clueDto.getContacterTel());
            cluecontacterDao.insert(cluecontacter);
        } else {
            Cluecontacter cluecontacter = MappingUtil.getSimpleMapperFacade().map(c, Cluecontacter.class);
            cluecontacter.setContacterName(clueDto.getContacterName());
            cluecontacterDao.updateById(cluecontacter);
        }

        return c;
    }

    protected Map<String, Object> getRemoteContactInfo(String id) {
        GetInfoByIdRequestDto getInfoByIdRequestDto = new GetInfoByIdRequestDto();
        getInfoByIdRequestDto.setId(id);

        return remoteDeveloperService.getContactInfo(getInfoByIdRequestDto);
    }

    @Override
    public ClueDto getClue(Map<String, Object> conditions) {

        QueryWrapper<Clue> queryWrapper = new QueryWrapper<>();
        conditions.forEach((key, value) -> {
            queryWrapper.eq(key, value);
        });

        queryWrapper.last("limit 1");
        Clue c = clueDao.selectOne(queryWrapper);

        return MappingUtil.getSimpleMapperFacade().map(c, ClueDto.class);
    }

    public ClueDto getClueBySource(GetClueSourceFollowRecordsRequestDto dto) {
        QueryWrapper<Clue> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ClueSource", dto.getClueSource());
        queryWrapper.eq("ClueSourceId", dto.getClueSourceId());
        queryWrapper.eq("ContacterTel", dto.getContacterTel());

        UUID userUUID = contextManager.fetchContextInfo().getUserContext().getUserId();
        queryWrapper.eq("ClueResponsiblePersonGUID", userUUID);

        List<Clue> c = clueDao.selectList(queryWrapper);

        if (c == null || c.size() == 0) {
            return new ClueDto();
        }

        return MappingUtil.getSimpleMapperFacade().map(c.get(0), ClueDto.class);
    }

    /**
     * 当前用户是否添加了这些东西
     *
     * @param clueSourceId
     * @return
     */
    public Set<String> isAdded(List<String> clueSourceId) {
        if (clueSourceId == null || clueSourceId.size() == 0) {
            return new HashSet<>();
        }
        UUID userUUID = contextManager.fetchContextInfo().getUserContext().getUserId();

        QueryWrapper<Clue> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ClueResponsiblePersonGUID", userUUID);
        queryWrapper.in("clueSourceId", clueSourceId);

        List<Clue> clues = clueDao.selectList(queryWrapper);
        Set<String> addedList = new HashSet<>();

        clues.forEach(c -> {
            addedList.add(c.getClueSourceId());
        });

        return addedList;
    }

    public FieldsSetting loadClueFields() {
        //硬编码的获取字段逻辑
        FieldsSetting fieldsSetting = new FieldsSetting();
        fieldsSetting.setIdField("ClueGUID");
        fieldsSetting.setFields(new ArrayList<>());
        String groupName = "clue";

        fieldsSetting.getFields().add(new DataApiField("clueDetail", groupName, "线索名称", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("clueSourceId", groupName, "线索来源ID", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("clueSource", groupName, "线索来源", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("clueSourceTitle", groupName, "线索来源标题", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("customerName", groupName, "客户名称", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("CustomerType", groupName, "客户类型", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("clueResponsiblePersonName", groupName, "负责人", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("FollowTime", groupName, "跟进时间", FieldType.Int));
        fieldsSetting.getFields().add(new DataApiField("contacterCount", groupName, "联系人数量", FieldType.Int));
        fieldsSetting.getFields().add(new DataApiField("clueStatus", groupName, "线索状态", FieldType.Int));
        fieldsSetting.getFields().add(new DataApiField("createdTime", groupName, "创建时间", FieldType.DateTime));
        fieldsSetting.getFields().add(new DataApiField("provinceName", groupName, "省份", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("provinceCode", groupName, "省份Code", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("areaCategoryName", groupName, "城市", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("areaCategoryCode", groupName, "城市code", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("creditCode", groupName, "统一信用代码", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("contacterTel", groupName, "联系人电话", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("contacterName", groupName, "联系人名称", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("keyword", groupName, "关键词", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("createdName", groupName, "线索创建人", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("createdTime", groupName, "线索创建时间", FieldType.DateTime));
        fieldsSetting.getFields().add(new DataApiField("ClueBUFullName", groupName, "部门名称", FieldType.DateTime));


        // 返回
        return fieldsSetting;
    }

    public ListDataResult myClue(LoadDataParams params) {
        UUID userId = contextManager.fetchContextInfo().getUserContext().getUserId();
        MyClueRequestDto dto = new MyClueRequestDto();

        dto.setUserId(userId);
        dto.setPage(params.getPageIndex() + 1);
        dto.setPageSize(params.getPageSize());
        dto.setOffset(params.getPageIndex() * dto.getPageSize());
        dto.addFilterByLoadDataApi(params.getOptions().getFilters());
        List<ClueDto> list = clueDao.findMyClueList(dto);
        TotalDto total = clueDao.findMyClueListTotal(dto);

        list.forEach(clue -> {
            QueryWrapper<Cluefollowrecord> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("ClueGUID", clue.getClueGUID().toString());
            queryWrapper.orderByDesc("CreatedTime");
            queryWrapper.last("limit 1");

            List<Cluefollowrecord> followList = cluefollowrecordDao.selectList(queryWrapper);
            if (followList != null && followList.size() > 0) {
                clue.setFollowerName(followList.get(0).getFollowerName());
                clue.setFollowTime(followList.get(0).getCreatedTime());
            } else {
                clue.setFollowerName("");
                clue.setFollowTime(null);
            }
        });

        ListDataResult result = new ListDataResult();
        result.setData(list);
        result.setTotal(total.getTotal());
        return result;
    }

    public ListDataResult regionClue(LoadDataParams params) {
        UUID userId = contextManager.fetchContextInfo().getUserContext().getUserId();
        MyClueRequestDto dto = new MyClueRequestDto();

        dto.setUserId(userId);
        dto.setPage(params.getPageIndex() + 1);
        dto.setPageSize(params.getPageSize());
        dto.setOffset(params.getPageIndex() * dto.getPageSize());
        dto.addFilterByLoadDataApi(params.getOptions().getFilters());
        List<ClueDto> list = clueDao.findRegionClueList(dto);
        TotalDto total = clueDao.findRegionClueListTotal(dto);

        list.forEach(clue -> {
            QueryWrapper<Cluefollowrecord> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("ClueGUID", clue.getClueGUID().toString());
            queryWrapper.orderByDesc("CreatedTime");
            queryWrapper.last("limit 1");

            List<Cluefollowrecord> followList = cluefollowrecordDao.selectList(queryWrapper);
            if (followList != null && followList.size() > 0) {
                clue.setFollowerName(followList.get(0).getFollowerName());
                clue.setFollowTime(followList.get(0).getCreatedTime());
            } else {
                clue.setFollowerName("");
                clue.setFollowTime(null);
            }
        });

        ListDataResult result = new ListDataResult();
        result.setData(list);
        result.setTotal(total.getTotal());
        return result;
    }

    public ClueDto clueDetail(UUID id) {
        Map<String, Object> condition = new HashMap<>();
        condition.put("clueGUID", id.toString());
        return getClue(condition);
    }

    public Boolean deleteClue(UUID id) {
        QueryWrapper<Clue> deleteWrapper = new QueryWrapper<>();
        UUID userId = contextManager.fetchContextInfo().getUserContext().getUserId();
        deleteWrapper.eq("ClueGUID", id);
        deleteWrapper.eq("ClueResponsiblePersonGUID", userId);
        Long isExist = clueDao.selectCount(deleteWrapper);
        if (isExist < 1) {
            throw new BusinessLogicException("操作失败，未找到相关线索");
        } else {
            clueDao.delete(deleteWrapper);
        }
        return true;
    }

    public List<Cluefollowprojectinfo> getClueProjects(UUID id) {
        QueryWrapper<Cluefollowprojectinfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("clueGUID", id);
        return cluefollowprojectinfoDao.selectList(queryWrapper);
    }

    public void addClueProject(Cluefollowprojectinfo cluefollowprojectinfo) {
        cluefollowprojectinfoDao.insert(cluefollowprojectinfo);
    }

    public void updateClueProject(Cluefollowprojectinfo cluefollowprojectinfo) {
        cluefollowprojectinfoDao.updateById(cluefollowprojectinfo);
    }

    public ClueFollowProjectInfoDto getClueProjectById(UUID id) {
        QueryWrapper<Cluefollowprojectinfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ClueFollowProjectInfoGUID", id);
        queryWrapper.last("limit 1");
        Cluefollowprojectinfo cluefollowprojectinfo = cluefollowprojectinfoDao.selectOne(queryWrapper);
        return MappingUtil.getSimpleMapperFacade().map(cluefollowprojectinfo, ClueFollowProjectInfoDto.class);
    }

    public void deleteClueProject(DeleteByIdRequestDto dto) {
        QueryWrapper<Cluefollowprojectinfo> deleteWrapper = new QueryWrapper<>();
        deleteWrapper.eq("ClueFollowProjectInfoGUID", dto.getId());
        deleteWrapper.last("limit 1");
        Cluefollowprojectinfo cluefollowprojectinfo = cluefollowprojectinfoDao.selectOne(deleteWrapper);
        if (cluefollowprojectinfo == null) {
            throw new BusinessLogicException("操作失败，未找到相关记录");
        } else {
            //先判断当前操作人是否有线索的权限，若有，才能删除线索下的联系人
            QueryWrapper<Clue> queryWrapperClue = new QueryWrapper<>();
            UUID userId = contextManager.fetchContextInfo().getUserContext().getUserId();
            queryWrapperClue.eq("ClueGUID", cluefollowprojectinfo.getClueGUID());
            queryWrapperClue.eq("ClueResponsiblePersonGUID", userId);
            Long isExist = clueDao.selectCount(queryWrapperClue);
            if (isExist < 1) {
                throw new BusinessLogicException("操作失败，无操作权限");
            } else {//删除线索联系人
                cluefollowprojectinfoDao.delete(deleteWrapper);
            }
        }
    }

    public List<OptionItem> searchCompanyQuery(SearchCompanyQueryRequestDto dto) {
        FuzzySearchReqDto fuzzySearchReqDto = new FuzzySearchReqDto();
        fuzzySearchReqDto.setKeyword(dto.getKeyword());
        LinkedHashMap fuzzySearchResult = fuzzySearchService.fuzzySearch(fuzzySearchReqDto);
        ArrayList data = (ArrayList) fuzzySearchResult.get("data");
        List<OptionItem> optionItemList = new ArrayList<OptionItem>();
        if (data != null && data.size() > 0) {
            for (int i = 0; i < data.size(); i++) {
                OptionItem item = new OptionItem();
                LinkedHashMap fuzzySearchItem = (LinkedHashMap) data.get(i); // 遍历 jsonarray 数组，把每一个对象转成 json 对象
                item.setText((String) fuzzySearchItem.get("supplier_name"));
                String creditCode = (String) fuzzySearchItem.get("credit_code");
                if (Objects.equals(creditCode, "")) {
                    continue;
                }
                item.setValue(creditCode);
                Map<String, Object> map = new HashMap<>();
                map.put("credit_code", fuzzySearchItem.get("credit_code"));
                item.setExtData(map);
                optionItemList.add(item);
            }
        }
        return optionItemList;
    }
}
